package com.imooc.bilibili.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.imooc.bilibili.exception.ConditionException;

import java.util.Calendar;
import java.util.Date;

/**
 * token 工具类
 */
public class TokenUtil {

    private static final String ISSUER = "签发者";

    /**
     * 生成 token 过期时间30分钟
     *
     * @param userId 用户唯一表示
     * @return 生成的 token
     * @throws Exception 生成异常
     */
    public static String generateToken(Long userId) throws Exception{
        // RSA 256 算法
        Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date()); // 设置当前时间
        calendar.add(Calendar.MINUTE, 30); // 30分钟过期
        return JWT.create()
                .withKeyId(String.valueOf(userId)) // 密钥Id 唯一Id
                .withIssuer(ISSUER) // 发行人
                .withExpiresAt(calendar.getTime()) // 过期时间
                .sign(algorithm); // 指定算法
    }

    /**
     * 生成刷新token,过期时间七天
     *
     * @param userId 用户id
     * @return token
     * @throws Exception 生成异常信息
     */
    public static String generateRefreshToken(Long userId) throws Exception{
        Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, 7);
        return JWT.create().withKeyId(String.valueOf(userId))
                .withIssuer(ISSUER)
                .withExpiresAt(calendar.getTime())
                .sign(algorithm);
    }

    /**
     * 验证 token 并返回 userId
     *
     * @param token token
     * @return userId
     */
    public static Long verifyToken(String token){
        try {
            Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey());
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            String keyId = jwt.getKeyId();
            return Long.valueOf(keyId);
        } catch (TokenExpiredException e) { // token 过期
            throw new ConditionException("555", "token过期!");
        } catch (Exception e) {
            throw new ConditionException("非法用户token!");
        }
    }
}
